package com.lyl.novel.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ClassUtil;
import com.lyl.novel.model.entity.Task;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 97134
 */
@Slf4j
@Component
public class QuartzUtils {
    /**
     * 定时任务调度程序
     */
    public static Scheduler staticScheduler;

    @Resource
    private Scheduler scheduler;


    @PostConstruct
    public void init() {
        staticScheduler = scheduler;
    }

    /**
     * 添加定时任务:创建后默认启动
     *
     * @param task 任务
     */
    public static boolean addJob(Task task) {
        boolean result = true;
        try {
            Class<? extends Job> jobClass = ClassUtil.loadClass(task.getBeanClass());
            // 构建定时任务信息
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup()).build();
            // 设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();
            // 构建触发器trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup()).withSchedule(scheduleBuilder).build();
            staticScheduler.scheduleJob(jobDetail, CollUtil.newHashSet(trigger), true);
        } catch (SchedulerException e) {
            log.error("添加定时任务异常", e);
            result = false;
        }
        return result;
    }

    public static boolean addSimpleJob(Task task, String startTime, String endTime, int intervalInSeconds, int repeatCount) {
        boolean result = true;
        try {
            Class<? extends Job> jobClass = ClassUtil.loadClass(task.getBeanClass());
            // 构建定时任务信息
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup()).build();
            // 构建触发器trigger
            SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())
                    .startAt(DateUtil.parse(startTime))
                    .endAt(DateUtil.parse(endTime))
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withIntervalInSeconds(intervalInSeconds)
                            .withRepeatCount(repeatCount)
                    )
                    .build();
            staticScheduler.scheduleJob(jobDetail, CollUtil.newHashSet(trigger), true);
        } catch (SchedulerException e) {
            log.error("添加定时任务异常", e);
            result = false;
        }
        return result;
    }

    public static boolean runOnce(Task task) {
        boolean result = true;
        if (checkExists(task.getJobName(), task.getJobGroup())) {
            return triggerJob(task);
        }
        try {
            Class<? extends Job> jobClass = ClassUtil.loadClass(task.getBeanClass());
            // 构建定时任务信息
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup()).build();
            // 构建触发器trigger
            SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withRepeatCount(0)
                    )
                    .build();
            staticScheduler.scheduleJob(jobDetail, CollUtil.newHashSet(trigger), true);
        } catch (SchedulerException e) {
            log.error("添加定时任务异常", e);
            result = false;
        }
        return result;
    }

    /**
     * 根据任务名称暂停定时任务
     *
     * @param name  job名称
     * @param group 组
     */
    public static boolean stopJob(String name, String group) {
        boolean result = true;
        try {
            staticScheduler.pauseJob(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            log.error("暂停定时任务异常", e);
            result = false;
        }
        return result;
    }

    /**
     * 暂停定时任务
     *
     * @param task 任务
     */
    public static boolean stopJob(Task task) {
        return stopJob(task.getJobName(), task.getJobGroup());
    }

    /**
     * 恢复定时任务
     *
     * @param name  任务名称
     * @param group 任务组
     */
    public static boolean resumeJob(String name, String group) {
        boolean result = true;
        try {
            staticScheduler.resumeJob(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            log.error("恢复定时任务异常", e);
            result = false;
        }
        return result;
    }

    /**
     * 检查任务是否存在
     *
     * @param name  任务名称
     * @param group 任务分组
     * @return true/false
     */
    public static boolean checkExists(String name, String group) {
        boolean exist;
        try {
            exist = staticScheduler.checkExists(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            exist = false;
        }
        return exist;
    }

    /**
     * 是否存在定时任务
     *
     * @param task 任务
     * @return true/false
     */
    public static boolean checkExists(Task task) {
        return checkExists(task.getJobName(), task.getJobGroup());
    }

    /**
     * 恢复定时任务
     *
     * @param task 定时任务
     */
    public static boolean resumeJob(Task task) {
        return resumeJob(task.getJobName(), task.getJobGroup());
    }

    /**
     * 运行一次定时任务
     *
     * @param name  任务名称
     * @param group 任务组
     */
    public static boolean triggerJob(String name, String group) {
        boolean result = true;
        try {
            staticScheduler.triggerJob(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            log.error("运行定时任务异常", e);
            result = false;
        }
        return result;
    }

    /**
     * 运行一次定时任务
     *
     * @param task 定时任务
     */
    public static boolean triggerJob(Task task) {
        return triggerJob(task.getJobName(), task.getJobGroup());
    }


    /**
     * 删除定时任务
     *
     * @param name  任务名称
     * @param group 任务组
     */
    public static boolean deleteJob(String name, String group) {
        boolean result = true;
        try {
            staticScheduler.deleteJob(JobKey.jobKey(name, group));
        } catch (SchedulerException e) {
            log.error("删除定时任务异常", e);
            result = false;
        }
        return result;
    }

    /**
     * 删除定时任务
     *
     * @param task 任务
     */
    public static boolean deleteJob(Task task) {
        return deleteJob(task.getJobName(), task.getJobGroup());
    }

    /**
     * 更新定时任务
     *
     * @param task 任务
     */
    public static boolean updateJob(Task task) {
        boolean result = true;
        try {
            //获取到对应任务的触发器
            TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
            //设置定时任务执行方式
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
            //重新构建任务的触发器trigger
            CronTrigger trigger = (CronTrigger) staticScheduler.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            //重置对应的job
            staticScheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            log.error("更新定时任务异常", e);
            result = false;
        }
        return result;
    }

    public static Map<String, String> getExecutingJobs() {
        Set<JobKey> allJobKeys = new HashSet<>();
        try {
            staticScheduler.getJobGroupNames()
                    .forEach(groupName -> {
                        try {
                            allJobKeys.addAll(staticScheduler.getJobKeys(GroupMatcher.groupEquals(groupName)));
                        } catch (SchedulerException e) {
                            e.printStackTrace();
                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return allJobKeys.stream().collect(Collectors.toMap(jobKey -> jobKey.getGroup(), jobKey -> jobKey.getName()));
    }

    public static List<String> getJobInfo() throws SchedulerException {
        List<String> jobInfoList = new ArrayList<>();
        List<String> jobGroupNames = staticScheduler.getJobGroupNames();
        for (String jobGroupName : jobGroupNames) {
            Set<JobKey> jobKeys = staticScheduler.getJobKeys(GroupMatcher.groupEquals(jobGroupName));
            for (JobKey jobKey : jobKeys) {
                Trigger.TriggerState state = staticScheduler.getTriggerState(TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup()));
                jobInfoList.add("任务名称：" + jobKey.getName() + ", 任务分组：" + jobKey.getGroup() + ", 状态：" + state);
            }
        }
        return jobInfoList;
    }

    public static String getState(String name, String group) {
        Trigger.TriggerState triggerState;
        try {
            triggerState = staticScheduler.getTriggerState(TriggerKey.triggerKey(name, group));
        } catch (SchedulerException e) {
            triggerState = Trigger.TriggerState.NONE;
        }
        return triggerState.name();
    }
}
